Element Binding
Data binding also allows you to
create bindings that allow you to create a linkage between XAML
elements. This is called Element Binding. To use element binding, you
can specify the ElementName as part of the binding syntax like so:
<Slider Minimum="10"
Maximum="36"
x:Name="fontSizeSlider" />
<TextBox FontSize="{Binding Value, ElementName=fontSizeSlider}"
Text="Make It Grow" />
The size of the font in the TextBox is being set based on the value of the Slider (named fontSizeSlider).
In this way you can use elements in the XAML to supply data to other
elements in the XAML. A more conventional use of element binding is to
set the data context of a container based on the selected value of a
control like so:
<ListBox ItemsSource="{Binding Games}"
x:Name="theList" />
<StackPanel DataContext="{Binding SelectedItem, ElementName=theList}">
<TextBlock>Name</TextBlock>
<TextBox Text="{Binding Name}" />
<TextBlock>Phone Number</TextBlock>
<TextBox Text="{Binding Phone}" />
</StackPanel>
In this example, the StackPanel is setting its DataContext to whatever item is selected in the ListBox. In this way you can show and/or edit the data in the StackPanelListBox. based on the selection of the
Converters
Data binding takes
properties from objects and moves them into properties on controls. At
times the types of the properties will not match or need some level of
manipulation to work. That is where converters come in. Converters are
stateless classes that can perform specific conversions during the
binding process. In order to be a converter, a class must implement the
IValueConverter interface. This
interface has two methods: Convert and ConvertBack to allow for
conversions in both directions during binding. For example, a simple
converter to make dates show up as short date strings looks like so:
public class DateConverter : IValueConverter
{
public object Convert(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
if (targetType == typeof(string) &&
value.GetType() == typeof(DateTime))
{
return ((DateTime)value).ToShortDateString();
}
// No Conversion
return value;
}
public object ConvertBack(object value,
Type targetType,
object parameter,
CultureInfo culture)
{
if (targetType == typeof(DateTime) &&
value.GetType() == typeof(string))
{
DateTime newDate;
if (DateTime.TryParse((string)value, out newDate))
{
return newDate;
}
}
// No Conversion
return value;
}
}
Converters are created as resources (usually at the application level) like so:
<Application x:Class="PhoneControls.App"
xmlns="..."
xmlns:x="..."
xmlns:phone="..."
xmlns:shell="..."
xmlns:my="clr-namespace:PhoneControls">
<Application.Resources>
<my:DateConverter x:Key="dateConverter" />
</Application.Resources>
...
</Application>
By creating the converter
at the application level, it can be used throughout the entire
application. Finally we can now use the converter directly in our data
binding like so:
<StackPanel DataContext="{Binding SelectedItem, ElementName=theList}">
<TextBlock>Name</TextBlock>
<TextBox Text="{Binding Name, Mode=TwoWay}" />
<TextBlock>Phone Number</TextBlock>
<TextBox Text="{Binding PhoneNumber, Mode=TwoWay}" />
<TextBlock>Phone Number</TextBlock>
<TextBox Text="{Binding ReleaseDate,
Mode=TwoWay,
Converter={StaticResource dateConverter}}" />
</StackPanel>
During the conversion of the underlying data (in this case a DateTime) the DateConverter class is used. When moving the data from the source to the control, the Convert is called; when the data is pushed back to the source, the ConvertBack method is called. Like this example, converters are often used just for formatting and not real conversion.
Data Binding Errors
By design, data binding errors
do not cause exceptions. This behavior is desirable because the source
of a data binding may enter a valid and invalid state a lot during the
life of your application. Let’s take the example we saw earlier where
we have a list of controls bound to the SelectedItem of a ListBox. When there is no selection in the ListBox
the data binding is failing. Throwing an exception is that case would
be the wrong thing to do. So as a developer you will need to need a way
to actually see data binding failures. Luckily you can see them pretty
clearly in the Visual Studio Output Window. When running your
application, you can use the View menu to show the Output Window as
shown in Figure 3.
When data binding fails, it adds a debug message to the output window. For example, if you used the wrong path in a Binding (e.g. Title instead of Name) you could see this in the Output Window as seen in Figure 4.
It’s not only binding errors
like bad paths that show up in the Output Window, but also bad
conversions (really any exception). For example, if a user attempted to
enter a bad date (e.g. 2/31/2010) into a date field, the output window
shows that error too during data binding (as seen in ).